package com.yc.anno.mybatis;

import lombok.Data;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;

class sqlSession{
    public <T> T getMapper(Class<T> clazz){
//        UserMapper mapper=getMapper(UserMapper.class);
//        JDK动态代理
//        创建代理对象
       return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
                new Class[]{clazz},
               //InvocationHandler方法拦截器，返回值就是业务方法的返回值
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy,//动态生成的代理对象
                                         Method method,//执行的方法
                                         Object[] args//执行方法的参数
                    ) throws Throwable {
                        System.out.println("method = " + method);
                        System.out.println("Arrays.toString(args) = " + Arrays.toString(args));
                        System.out.println("method.getReturnType() = " + method.getReturnType());

                        Select select=method.getAnnotation(Select.class);
                        if(select!=null){
                            //这是查询方法
                            String sql=select.value();
                            if(method.getParameterCount()==1){
                                //单参数
                                String sql2=select.value();
                                System.out.println("sql2 = " + sql2);
                                //排查实体对象
                                sql2=sql2.replaceAll("#\\{\\w+}","?");
                                System.out.println("sql2 = " + sql2);
                                System.out.println("参数="+Arrays.toString(args));
                                System.out.println("执行语句省略");
                            }else{

                            }
                        }
                        return null;
                    }
                });
    }

    public static void main(String[] args) {
        sqlSession sqlSession = new sqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.selectById(100);
        userMapper.selectLikeName("张三");

    }
}
// 实体类
@Data
class User{
    Integer id;
    String username;
    String password;
}
// Mapper 接口
interface UserMapper {
    @Insert("insert into test_user (username, password) values(#{usr},#{pwd})")
    void insert(@Param("usr") String username, @Param("pwd") String password);
    @Update("update test_user set username = #{username}, password = #{password} where id = #{id}")
    int update(User user);
    @Select("select * from test_user where id = #{id}")
    User selectById(int id);
    @Select("select * from test_user where username like #{uname}")
    List< User > selectLikeName(String username);
}
// 提示: 如何获取方法返回值泛型类型? 请参考以下代码
class Demo {
    public static void main(String[] args) throws Exception {
        // 获取 selectLikeName 方法返回值 List 的泛型
        Class aClass = getGenericReturnType(UserMapper.class,
                "selectLikeName",
                String.class);
        System.out.println("返回值List的泛型类型 = " + aClass);
    }
    public static Class getGenericReturnType(Class cls, String methodName,Class...classes){
        try{
            // 获取方法对象
            Method declaredMethod = cls.getDeclaredMethod(methodName, classes);
            // 获取返回值类型 Type (注意:Type不是Class)
            Type type = declaredMethod.getGenericReturnType();
            // 转型 ParameterizedType
            ParameterizedType pType=(ParameterizedType)type;
            // 获取泛型数组中的第一个泛型类型
            Class ret = (Class) pType.getActualTypeArguments()[0];
            return ret;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
@Retention(RetentionPolicy.RUNTIME)
@interface Insert{
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Select{
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Update{
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Delete{
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Param{
    String value();
}

